﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Frame.Lib.Core.Base;
using Frame.Lib.Utilities;
using Frame.Lib.Enums;


namespace Frame.Lib.Core.Tree
{
    public class TreeDAL<Info> : CommonOperate<Info>, ITree<Info> where Info : class,new()
    {
        private string _tableName;

        private BaseDAL _tree;

        protected override BaseDAL DAL
        {
            get
            {
                return _tree;
            }
        }

        public TreeDAL(string tableName)
            : base(tableName)
        {
            _tree = new BaseDAL();
            this._tableName = tableName;
        }



        #region ITree<Info> 成员

        public void Move(List<int> lstSrcIDs, object destID)
        {
            if (lstSrcIDs.Count == 0)
            {
                return;
            }
            string strSqlSrc = "select Depth, Path from " + _tableName + " where ID=" + lstSrcIDs[0];

            TreeInfo src = dbOper.Query<TreeInfo>(strSqlSrc).First();

            int iDepthSrc = (int)src.Depth;
            string strPathSrc = (string)src.Path;

            string strSqlDest = "select ID,UpperID, Depth, Path from " + _tableName + " where ID =" + destID;

            TreeInfo dest = dbOper.Query<TreeInfo>(strSqlDest).First();
            int iDepthNew = (int)dest.Depth + 1;
            int iDepthDiff = iDepthNew - iDepthSrc;
            string strPathNew = (string)dest.Path + dest.ID + ",";

            StringBuilder sbSqls = new StringBuilder();
            for (int i = 0; i < lstSrcIDs.Count; i++)
            {
                sbSqls.Append("update " + _tableName + " set Depth=Depth+" + iDepthDiff + ",Path=replace(path,'" + strPathSrc + "','" + strPathNew + "') where path like '%" + strPathSrc + lstSrcIDs[i] + ",%';");
            }

            string strSrcIDs = ConvertUtil.ConvertToDbStr(lstSrcIDs);
            sbSqls.Append("update " + _tableName + " set depth=" + iDepthNew + ",path='" + strPathNew + "',UpperID=" + destID + " where ID in (" + strSrcIDs + ")");

            dbOper.RunSql(sbSqls.ToString());
        }

        public List<int> GetSubIDs(int upperID)
        {
            string strSql = "select ID from " + _tableName + " where Path like @p0";

            IEnumerable<int> ids = dbOper.Query<int>(strSql,"%," + upperID + ",%");

            List<int> lstIDs = new List<int>(ids);
            lstIDs.Add(Convert.ToInt32(upperID));
            return lstIDs;
        }

        /// <summary>
        /// 没有去重的功能
        /// </summary>
        /// <param name="lstUpperIDs"></param>
        /// <returns></returns>
        public List<int> GetSubIDs(IEnumerable<int> lstUpperIDs)
        {
            string strSql = "select ID ,Path from " + _tableName;
            List<TreeInfo> infos = dbOper.Query<TreeInfo>(strSql);

            List<int> lstIDs = new List<int>();

            foreach (int iUpperID in lstUpperIDs)
            {
                lstIDs.Add(iUpperID);
                IEnumerable<int> ids = from info in infos
                                       where info.Path.Contains("," + iUpperID + ",")
                                       select (int)info.ID;

                lstIDs.AddRange(ids);

            }
            return lstIDs;
        }

        public virtual int GetRootID()
        {
            string strSql = "select ID from " + _tableName + " where UpperID = 0";
            List<int> ids = dbOper.Query<int>(strSql).ToList();

            int rootID;

            if (ids.Count() == 0)
            {
                AddRoot(Constants.DEFAULT_ROOT_NAME);
                rootID = (int)GetRootID();
            }
            else
            {
                rootID = ids.First();
            }

            return rootID;
        }

        private void AddRoot(string name)
        {
            string strSql = "insert into " + _tableName + " (ID,[Name],UpperID,path,depth) " +
                            "values(1,'" + name + "',0,',',0);";
            dbOper.RunSql(strSql);
        }

        public bool Exist(object upperID, string name, object id)
        {
            string strSql = "select count(*) from " + _tableName + " where UpperID = @p0 and [Name] =@p1";

            IEnumerable<int> count = null;

            if (id != null && id.ToString() != "")
            {
                strSql += " and ID != @p2";
                count = dbOper.Query<int>(strSql, upperID, name, id);
            }
            else
            {
                count = dbOper.Query<int>(strSql, upperID, name);
            }

            bool flag = (count.First() > 0) ? true : false;
            return flag;
        }

        public virtual List<Info> GetList(int upperID)
        {
            string strSql = "select * from " + _tableName + " where UpperID = @p0 order by Orders";
            List<Info> list = dbOper.Query<Info>(strSql, upperID);
            return list;
        }

        public virtual DataTable GetDataTable(object upperID)
        {
            string strSql = "select * from " + _tableName + " where UpperID = @p0 order by Orders";
            DataTable dt = dbOper.Query(strSql, upperID);
            return dt;
        }

        /// <summary>
        /// 获得指定根下的所有列表
        /// </summary>
        /// <param name="rootID"></param>
        /// <returns></returns>
        protected virtual List<Info> GetTreeList(object rootID)
        {
            string sql = "select * from " + _tableName + " where ID = " + rootID + " or Path like '%," + rootID + ",%'";
            List<Info> list = dbOper.Query<Info>(sql);
            return list;
        }

        public int GetID(object upperID, string name)
        {
            string strSql = "select " + TableField.ID + " from " + _tableName + " where UpperID = @p0 and [Name] = @p1";
            int id = dbOper.Query<int>(strSql, upperID, name).First();
            return id;
        }

        public int GetUpperID(object id)
        {
            string strSql = "select UpperID from " + _tableName + " where ID = @p0";
            int upperID = dbOper.Query<int>(strSql, id).First();
            return upperID;
        }
        #endregion

        public List<int> GetParentIDs(List<int> lstDeptIDs)
        {
            string strSubIDs = ConvertUtil.ConvertToDbStr(lstDeptIDs);
            string strSql = "select ID, Path from " + _tableName + " where ID in (" + strSubIDs + ")";
            List<int> lstParentIDs = new List<int>();
            DataTable dt = dbOper.Query(strSql);
            foreach (DataRow dr in dt.Rows)
            {
                List<int> lstTmp = StrUtil.SplitToInt(dr["Path"].ToString());
                for (int i = 0; i < lstTmp.Count; i++)
                {
                    if (lstParentIDs.IndexOf(lstTmp[i]) < 0)
                    {
                        lstParentIDs.Add(lstTmp[i]);
                    }
                }
                lstParentIDs.Add((int)dr["ID"]);//把自己加上
            }
            return lstParentIDs;
        }

        public bool HasChild(int upperID)
        {
            string sql = "select count(*) from " + _tableName + " where UpperID = @p0";
            int count = dbOper.GetScalar<int>(sql, upperID);
            bool flag = (count == 0) ? false : true;
            return flag;
        }
    }
}